package dev.ahamed.mva.sample.slice;

import dev.ahamed.mva.sample.ResourceTable;
import dev.ahamed.mva.sample.data.DataManager;
import dev.ahamed.mva.sample.view.impl.ISwipeToDismissListener;

import mva2.adapter.ultimateprovider.Model;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.multimodalinput.event.TouchEvent;
import ohos.utils.IntentConstants;
import ohos.utils.net.Uri;

import java.io.IOException;
import java.util.List;

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_PARENT;

/**
 * AbsAbilitySlice
 *
 * @since 2021.07.08
 */
public abstract class AbsAbilitySlice extends AbilitySlice implements Component.ClickedListener,
        ISwipeToDismissListener {
    /**
     * FEATURE_BASIC
     */
    protected static final int FEATURE_BASIC = 0;
    /**
     * FEATURE_ADVANCED
     */
    protected static final int FEATURE_ADVANCED = 1;
    /**
     * FEATURE_SELECTION
     */
    protected static final int FEATURE_SELECTION = 2;
    /**
     * FEATURE_EXPANSION
     */
    protected static final int FEATURE_EXPANSION = 3;
    /**
     * FEATURE_DECORATION
     */
    protected static final int FEATURE_DECORATION = 4;
    /**
     * FEATURE_TREESECTION
     */
    protected static final int FEATURE_TREESECTION = 5;
    /**
     * FEATURE_NEWSFEED
     */
    protected static final int FEATURE_NEWSFEED = 6;
    /**
     * FEATURE_FEATURES
     */
    protected static final int FEATURE_FEATURES = 7;
    /**
     * ANIMATOR_DURATION
     */
    protected static final int ANIMATOR_DURATION = 200;

    private static final int SHOW_MENU_FEATURE = 100;
    private static final int HIDE_MENU_FEATURE = 101;
    private static final int SHOW_MENU_CONFIG = 102;
    private static final int HIDE_MENU_CONFIG = 103;
    private static final int SHOW_MENU_MORE = 104;
    private static final int HIDE_MENU_MORE = 105;

    /**
     * ListContainer
     */
    protected ListContainer mListContainer;
    /**
     * ScrollView
     */
    protected ScrollView mScrollView;
    /**
     * DecorComponent
     */
    protected Component mDecorComponent;
    /**
     * MenuConfig
     */
    protected DependentLayout mMenuConfig;
    /**
     * DataManager
     */
    protected final DataManager mDataManager = new DataManager();

    private Component mBgCloseMenu;
    private DirectionalLayout mBottomMenuFeature;
    private Text mTvMenuFeature;
    private DirectionalLayout mMenuFeature;
    private Text mTvBasic;
    private Text mTvAdvanced;
    private Text mTvSelection;
    private Text mTvExpansion;
    private Text mTvDecoration;
    private Text mTvTreesection;
    private Text mTvNewsfeed;
    private Text mTvFeatures;
    private AnimatorProperty mMenuFeatureHideAnimator;
    private AnimatorProperty mMenuFeatureShowAnimator;
    private Text mTvMenuConfig;
    private AnimatorProperty mMenuConfigHideAnimator;
    private AnimatorProperty mMenuConfigShowAnimator;
    private Text mTvMenuMore;
    private DirectionalLayout mMenuMore;
    private Text mTvSwitchTheme;
    private Text mTvToggleHints;
    private Text mTvRateApp;
    private Text mTvGitHub;
    private AnimatorProperty mMenuMoreHideAnimator;
    private AnimatorProperty mMenuMoreShowAnimator;
    private String[] mSampleSections;

    private MyEventHandler mHandler = new MyEventHandler(EventRunner.getMainEventRunner());
    private StackLayout mDecorLayout = new StackLayout(this);

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        initView();

        initData();
    }

    private void initView() {
        StackLayout.LayoutConfig config = new StackLayout.LayoutConfig(MATCH_PARENT, MATCH_PARENT);
        mDecorLayout.setLayoutConfig(config);
        mDecorComponent = LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_ability_main, null, false);
        mListContainer = (ListContainer) mDecorComponent.findComponentById(ResourceTable.Id_listContainer);
        mScrollView = (ScrollView) mDecorComponent.findComponentById(ResourceTable.Id_scrollView);
        mDecorLayout.addComponent(mDecorComponent);
        super.setUIContent(mDecorLayout);
        mBottomMenuFeature = (DirectionalLayout) findComponentById(ResourceTable.Id_bottom_menu_feature);
        mTvMenuFeature = (Text) findComponentById(ResourceTable.Id_tv_menu_feature);
        initStrArray();
        mMenuFeature = (DirectionalLayout) findComponentById(ResourceTable.Id_home_menu_feature);
        mTvBasic = (Text) findComponentById(ResourceTable.Id_tv_basic);
        mTvBasic.setText(mSampleSections[FEATURE_BASIC]);
        mTvAdvanced = (Text) findComponentById(ResourceTable.Id_tv_advanced);
        mTvAdvanced.setText(mSampleSections[FEATURE_ADVANCED]);
        mTvSelection = (Text) findComponentById(ResourceTable.Id_tv_selection);
        mTvSelection.setText(mSampleSections[FEATURE_SELECTION]);
        mTvExpansion = (Text) findComponentById(ResourceTable.Id_tv_expansion);
        mTvExpansion.setText(mSampleSections[FEATURE_EXPANSION]);
        mTvDecoration = (Text) findComponentById(ResourceTable.Id_tv_decoration);
        mTvDecoration.setText(mSampleSections[FEATURE_DECORATION]);
        mTvTreesection = (Text) findComponentById(ResourceTable.Id_tv_treesection);
        mTvTreesection.setText(mSampleSections[FEATURE_TREESECTION]);
        mTvNewsfeed = (Text) findComponentById(ResourceTable.Id_tv_newsfeed);
        mTvNewsfeed.setText(mSampleSections[FEATURE_NEWSFEED]);
        mTvFeatures = (Text) findComponentById(ResourceTable.Id_tv_features);
        mTvFeatures.setText(mSampleSections[FEATURE_FEATURES]);
        mTvMenuConfig = (Text) findComponentById(ResourceTable.Id_tv_menu_config);
        mMenuConfig = (DependentLayout) findComponentById(ResourceTable.Id_home_menu_config);
        mTvMenuMore = (Text) findComponentById(ResourceTable.Id_tv_menu_more);
        mMenuMore = (DirectionalLayout) findComponentById(ResourceTable.Id_home_menu_more);
        mTvSwitchTheme = (Text) findComponentById(ResourceTable.Id_tv_switchtheme);
        mTvToggleHints = (Text) findComponentById(ResourceTable.Id_tv_togglehints);
        mTvToggleHints.setEnabled(false);
        mTvRateApp = (Text) findComponentById(ResourceTable.Id_tv_rateapp);
        mTvGitHub = (Text) findComponentById(ResourceTable.Id_tv_github);
        mBgCloseMenu = findComponentById(ResourceTable.Id_bg_closemenu);
        initListener();
        initAnimator();
    }

    private void initListener() {
        mBottomMenuFeature.setClickedListener(component -> {
            setMenuFeatureVisible(true);
        });
        mTvBasic.setClickedListener(this::onClick);
        mTvAdvanced.setClickedListener(this::onClick);
        mTvSelection.setClickedListener(this::onClick);
        mTvExpansion.setClickedListener(this::onClick);
        mTvDecoration.setClickedListener(this::onClick);
        mTvTreesection.setClickedListener(this::onClick);
        mTvNewsfeed.setClickedListener(this::onClick);
        mTvFeatures.setClickedListener(this::onClick);
        mTvMenuConfig.setClickedListener(component -> {
            setMenuConfigVisible(mMenuConfig.getVisibility() == Component.VISIBLE ? false : true);
        });
        mTvMenuMore.setClickedListener(component -> {
            setMenuMoreVisible(true);
        });
        mTvSwitchTheme.setClickedListener(this::onClick);
        mTvToggleHints.setClickedListener(this::onClick);
        mTvRateApp.setClickedListener(this::onClick);
        mTvGitHub.setClickedListener(this::onClick);
        mBgCloseMenu.setTouchEventListener((component, touchEvent) -> {
            if (mMenuFeature.getVisibility() != Component.HIDE) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    setMenuFeatureVisible(false);
                }
                return true;
            }
            if (mMenuMore.getVisibility() != Component.HIDE) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    setMenuMoreVisible(false);
                }
                return true;
            }
            return false;
        });
    }

    /**
     * 设置menu消失的动画
     */
    private void initAnimator() {
        mMenuFeatureHideAnimator = mMenuFeature.createAnimatorProperty();
        mMenuFeatureHideAnimator.alpha(0).setDuration(ANIMATOR_DURATION);
        mMenuFeatureShowAnimator = mMenuFeature.createAnimatorProperty();
        mMenuFeatureShowAnimator
                .scaleXFrom(0).scaleX(1)
                .scaleYFrom(0).scaleY(1)
                .alphaFrom(0).alpha(1)
                .setDuration(ANIMATOR_DURATION);

        mMenuConfigHideAnimator = mMenuConfig.createAnimatorProperty();
        mMenuConfigHideAnimator.alpha(0).setDuration(ANIMATOR_DURATION);
        mMenuConfigShowAnimator = mMenuConfig.createAnimatorProperty();
        mMenuConfigShowAnimator
                .scaleXFrom(0).scaleX(1)
                .scaleYFrom(0).scaleY(1)
                .alphaFrom(0).alpha(1)
                .setDuration(ANIMATOR_DURATION);

        mMenuMoreHideAnimator = mMenuMore.createAnimatorProperty();
        mMenuMoreHideAnimator.alpha(0).setDuration(ANIMATOR_DURATION);
        mMenuMoreShowAnimator = mMenuMore.createAnimatorProperty();
        mMenuMoreShowAnimator
                .scaleXFrom(0).scaleX(1)
                .scaleYFrom(0).scaleY(1)
                .alphaFrom(0).alpha(1)
                .setDuration(ANIMATOR_DURATION);
    }

    /**
     * 设置菜单栏显示/隐藏
     *
     * @param visible 控件是否可见
     */
    public void setMenuFeatureVisible(boolean visible) {
        if (visible) {
            mHandler.sendEvent(SHOW_MENU_FEATURE);
            mMenuFeatureShowAnimator.start();
        } else {
            mMenuFeatureHideAnimator.start();
            mHandler.sendEvent(HIDE_MENU_FEATURE, ANIMATOR_DURATION);
        }
    }

    /**
     * 设置页面底部更多菜单是否可见
     *
     * @param visible 控件是否可见
     */
    public void setMenuMoreVisible(boolean visible) {
        if (visible) {
            mHandler.sendEvent(SHOW_MENU_MORE);
            mMenuMoreShowAnimator.start();
        } else {
            mMenuMoreHideAnimator.start();
            mHandler.sendEvent(HIDE_MENU_MORE, ANIMATOR_DURATION);
        }
    }

    /**
     * 设置页面底部设置菜单是否可见
     *
     * @param visible 控件是否可见
     */
    public void setMenuConfigVisible(boolean visible) {
        if (visible) {
            mHandler.sendEvent(SHOW_MENU_CONFIG);
            mMenuConfigShowAnimator.start();
        } else {
            mMenuConfigHideAnimator.start();
            mHandler.sendEvent(HIDE_MENU_CONFIG, ANIMATOR_DURATION);
        }
    }

    /**
     * abstract initData
     */
    public abstract void initData();

    /**
     * abstract configUpdate
     */
    public abstract void configUpdate();

    /**
     * abstract initConfig
     */
    public abstract void initConfig();

    /**
     * abstract doItemDismissed
     *
     * @param position item角标
     */
    public abstract void doItemDismissed(int position);

    /**
     * abstract getModels
     *
     * @return 适配器List数组
     */
    public abstract List<Model> getModels();

    /**
     * initStrArray
     */
    protected void initStrArray() {
        try {
            mSampleSections = getContext().getResourceManager().getElement(
                    ResourceTable.Strarray_sample_section).getStringArray();
        } catch (IOException | NotExistException | WrongTypeException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置菜单文字
     *
     * @param index 菜单的位置
     */
    public void setTvMenuFeatureText(int index) {
        mTvMenuFeature.setText(mSampleSections[index]);
    }

    /**
     * 设置菜单是否可见
     */
    public void setTvMenuConfigVisible() {
        mTvMenuConfig.setVisibility(Component.VISIBLE);
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mMenuFeatureHideAnimator != null) {
            mMenuFeatureHideAnimator.release();
        }
        if (mMenuFeatureShowAnimator != null) {
            mMenuFeatureShowAnimator.release();
        }
        if (mMenuConfigHideAnimator != null) {
            mMenuConfigHideAnimator.release();
        }
        if (mMenuConfigShowAnimator != null) {
            mMenuConfigShowAnimator.release();
        }
        if (mMenuMoreHideAnimator != null) {
            mMenuMoreHideAnimator.release();
        }
        if (mMenuMoreShowAnimator != null) {
            mMenuMoreShowAnimator.release();
        }
    }

    /**
     * onBackPressed
     */
    @Override
    protected void onBackPressed() {
        if (mMenuFeature.getVisibility() == Component.VISIBLE) {
            setMenuFeatureVisible(false);
            return;
        }
        if (mMenuConfig.getVisibility() == Component.VISIBLE) {
            setMenuConfigVisible(false);
            return;
        }
        if (mMenuMore.getVisibility() == Component.VISIBLE) {
            setMenuMoreVisible(false);
            return;
        }
        super.onBackPressed();
    }

    /**
     * 点击事件
     *
     * @param component 响应点击事件的控件
     */
    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_tv_basic:
                if (!mSampleSections[FEATURE_BASIC].equals(mTvMenuFeature.getText())) {
                    present(new BasicAbilitySlice(), new Intent());
                    terminate();
                }
                break;
            case ResourceTable.Id_tv_expansion:
                if (!mSampleSections[FEATURE_EXPANSION].equals(mTvMenuFeature.getText())) {
                    present(new ExpansionAbilitySlice(), new Intent());
                    terminate();
                }
                break;
            case ResourceTable.Id_tv_decoration:
                if (!mSampleSections[FEATURE_DECORATION].equals(mTvMenuFeature.getText())) {
                    present(new DecorationAbilitySlice(), new Intent());
                    terminate();
                }
                break;
            case ResourceTable.Id_tv_newsfeed:
                if (!mSampleSections[FEATURE_NEWSFEED].equals(mTvMenuFeature.getText())) {
                    present(new NewsFeedAbilitySlice(), new Intent());
                    terminate();
                }
                break;
            case ResourceTable.Id_tv_features:
                if (!mSampleSections[FEATURE_FEATURES].equals(mTvMenuFeature.getText())) {
                    present(new HomeAbilitySlice(), new Intent());
                    terminate();
                }
                break;
            case ResourceTable.Id_tv_rateapp:
            case ResourceTable.Id_tv_github:
                jumpWeb(getString(ResourceTable.String_text_project_url));
                break;
            case ResourceTable.Id_bt_update:
                setMenuConfigVisible(false);
                configUpdate();
                break;
            case ResourceTable.Id_bt_reset:
                initConfig();
                setMenuConfigVisible(false);
                configUpdate();
                break;
            default:
                break;
        }
    }

    /**
     * 跳转浏览器
     *
     * @param urlString 网址
     */
    private void jumpWeb(String urlString) {
        Intent intents = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withUri(Uri.parse(urlString))
                .withAction(IntentConstants.ACTION_SEARCH)
                .build();
        intents.setOperation(operation);
        startAbility(intents);
    }

    /**
     * onItemDismissed
     *
     * @param position 位置
     * @param item 要删除的对象
     */
    @Override
    public void onItemDismissed(int position, Object item) {
        getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
            @Override
            public void run() {
                doItemDismissed(position);
            }
        });
    }

    private class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            switch (event.eventId) {
                case SHOW_MENU_FEATURE:
                    if (mMenuFeature != null && mBgCloseMenu != null) {
                        mMenuFeature.setVisibility(Component.VISIBLE);
                        mBgCloseMenu.setVisibility(Component.VISIBLE);
                    }
                    setViewVisible(mMenuMore, Component.HIDE);
                    break;
                case HIDE_MENU_FEATURE:
                    if (mMenuFeature != null && mBgCloseMenu != null) {
                        mMenuFeature.setVisibility(Component.HIDE);
                        mBgCloseMenu.setVisibility(Component.HIDE);
                    }
                    break;
                case SHOW_MENU_CONFIG:
                    setViewVisible(mMenuConfig, Component.VISIBLE);
                    setViewVisible(mMenuFeature, Component.HIDE);
                    setViewVisible(mMenuMore, Component.HIDE);
                    break;
                case HIDE_MENU_CONFIG:
                    setViewVisible(mMenuConfig, Component.HIDE);
                    break;
                case SHOW_MENU_MORE:
                    if (mMenuMore != null && mBgCloseMenu != null) {
                        mMenuMore.setVisibility(Component.VISIBLE);
                        mBgCloseMenu.setVisibility(Component.VISIBLE);
                    }
                    setViewVisible(mMenuFeature, Component.HIDE);
                    break;
                case HIDE_MENU_MORE:
                    if (mMenuMore != null && mBgCloseMenu != null) {
                        mMenuMore.setVisibility(Component.HIDE);
                        mBgCloseMenu.setVisibility(Component.HIDE);
                    }
                    break;
                default:
                    break;
            }
        }
    }

    private void setViewVisible(Component component, int visible) {
        if (component != null) {
            component.setVisibility(visible);
        }
    }

}
